<template>
    <div class="list" ref="listRef" @scroll="scrollBack">
        <div class="background" ref="backgroundRef"></div>
        <ul ref="ulRef" class="ul" :style="{ transform: `translateY(${translateTop}px)` }">
            <li v-for="item in list" :key="item.id">{{ item.id }}-{{ item.name }}</li>
        </ul>
    </div>
</template>
<script lang="ts">
import { defineComponent, reactive, toRefs, computed, ref, onMounted } from 'vue'
import { mockList } from './constant'
export default defineComponent({
    name: 'MockList',
    setup() {
        const components = {
            listRef: ref(),
            backgroundRef: ref(),
            ulRef: ref()
        }
        const constant = {
            mockList
        }
        const state = reactive({
            translateTop: 0, //ul的偏移量
            itemHeight: 30,
            visibleCount: 10,
            canSeeHeight: 300,
            list: mockList as { id: number; name: string }[]
        })
        const liStartCount = computed(() => {
            return Math.floor(state.translateTop / state.itemHeight)
        })
        onMounted(async () => {
            await methods.initBackGroundHeight()
        })
        const methods = {
            scrollBack(e: any) {
                const canScroll = liStartCount.value < constant.mockList.length - state.visibleCount
                let scrollHeight = e?.target?.scrollTop.toFixed(3)

                if (canScroll) {
                    // console.log(liStartCount.value)
                    state.translateTop = scrollHeight
                    methods.setStateList()
                } else {
                    if (scrollHeight < state.translateTop) {
                        state.translateTop = scrollHeight
                        methods.setStateList()
                    } else {
                        console.log('到底了')
                    }
                }
            },
            setStateList() {
                state.list = constant.mockList.slice(liStartCount.value, liStartCount.value + state.visibleCount)
            },
            async initBackGroundHeight() {
                components.backgroundRef.value.style.height = `${constant.mockList.length * state.itemHeight}px`
            }
        }
        return {
            ...toRefs(state),
            ...components,
            ...methods,
            ...constant
        }
    }
})
</script>
<style lang="scss" scoped>
.list {
    width: 800px;
    height: 300px;
    overflow-y: auto;
    border: 1px solid #1677ff;
    margin: auto;
    position: relative;
    padding: 0;
    .background {
        width: 100%;
    }
    .ul {
        width: 100%;
        height: 300px;
        position: absolute;
        padding: 0;
        top: 0;
        left: 0;
        z-index: 999;
        li {
            box-sizing: border-box;
            display: block;
            height: 30px;
            width: 100%;
            line-height: 30px;
            list-style: none;
            cursor: pointer;
            padding: 0 20px;
            &:hover {
                background: #1677ff;
                color: #fff;
            }
        }
    }
}
</style>
